

#include "mev.h"
#include "kev.h"
#include <iostream>
#include "solid.h"
#include "hedmodel.h"
#include "face.h"
#include "loop.h"
#include "point.h"
#include "vertex.h"
#include "edge.h"
#include "halfedge.h"


MEV::MEV(HEDModel& _model, int _s, int _v1, int _v4, double _x, double _y, double _z)
: he1( NULL )
, he2( NULL )
, model( &_model )
, v1( _v1 )
, v( _v4 )
, x( _x )
, y( _y )
, z( _z )
{
  Vertex* vtx = _model.getVertex( _v1 );
  //HalfEdge* he = _model.getHalfEdge( vtx, _x, _y, _z );
  HalfEdge* he = _model.getHalfEdgeNEW( vtx, _x, _y, _z );
  //he = he->getPrv()->mate();
  int nFct = he->getLoop()->getFace()->getFaceno();
  int nVtx = _v1;
  if( he->getEdg() != NULL )
    nVtx = he->mate()->getVtx()->getVertexno();
  this->checksInputData(_model, _s, nFct, nFct, _v1, nVtx, nVtx);
}


MEV::MEV(HEDModel& _model, int _s, int _f1, int _f2, int _v1, int _v2, int _v3, int _v4, double _x, double _y, double _z)
: he1( NULL )
, he2( NULL )
, v( _v4 )
, x( _x )
, y( _y )
, z( _z )
{
  this->checksInputData(_model, _s, _f1, _f2, _v1, _v2, _v3);
}


MEV::MEV(HalfEdge* _he1, HalfEdge* _he2, int _v, double _x, double _y, double _z)
: he1( _he1 )
, he2( _he2 )
, v( _v )
, x( _x )
, y( _y )
, z( _z )
{

}



void
MEV::execute()
{
  std::cout << "\nMEV::execute() \n";

  if( (he1 == NULL) && (he2 == NULL) )
  {
    Vertex* vtx = model->getVertex( v1 );
    //HalfEdge* he = _model.getHalfEdge( vtx, _x, _y, _z );
    HalfEdge* he = model->getHalfEdgeNEW( vtx, x, y, z );
    //he = he->getPrv()->mate();
    int nFct = he->getLoop()->getFace()->getFaceno();
    int nVtx = v1;
    if( he->getEdg() != NULL )
      nVtx = he->mate()->getVtx()->getVertexno();
    this->checksInputData(*model, 1, nFct, nFct, v1, nVtx, nVtx);
  }

  Loop* loop = he1->getLoop();
  Face* face = loop->getFace();
  Solid* solid = face->getSolid();
  Edge* newedge = new Edge(solid);
  Point* point = new Point(x,y,z);
  Vertex* newvertex = new Vertex(point,solid);
  newvertex->setVertexno(v);
  HalfEdge* he = he1;
  while(he != he2)
  {
    he->setVtx(newvertex);
    he = he->mate()->getNxt();
  }
  // Original [MANT1988] code...
  //newedge->addhe(newvertex, he2, PLUS); 
  //newedge->addhe(he2->getVtx(), he1, MINUS);
  // Modified code...
  newedge->addhe(he2->getVtx(), he1, MINUS);
  newedge->addhe(newvertex, he2, PLUS); 
  newvertex->setVedge(he2->getPrv());
  he2->getVtx()->setVedge(he2);

  edge = newedge;
}



void
MEV::unExecute()
{
  std::cout << "\nMEV::unExecute() TESTING!\n";
  // checks the correct order of the half-edges that should be sent to KEV
  HalfEdge* h1 = NULL;
  HalfEdge* h2 = NULL;
  if( edge->getHe1()->getVtx()->getVertexno() == v )
  {
    h1 = edge->getHe1();  h2 = edge->getHe2();
  }
  else
  {
    h1 = edge->getHe2();  h2 = edge->getHe1();
  }

  KEV kev( h1, h2 );
  kev.execute();

  // cleaning
  he1 = NULL;
  he2 = NULL;
  edge = NULL;
}



void
MEV::checksInputData(HEDModel& _model, int _s, int _f1, int _f2, int _v1, int _v2, int _v3)
{
  Solid* oldsolid = NULL;
  Face* oldface1 = NULL;
  Face* oldface2 = NULL;
  if((oldsolid = _model.getsolid(_s)) == NULL)
  {
    std::cout << "mev: solid " << _s << " not found. \n";
    //return(ERROR);
  }
  if( (oldface1 = _model.fface(oldsolid,_f1)) == NULL)
  {
    std::cout << "mev: face " << _f1 << " not found in solid " << _s << ". \n";
    //return(ERROR);
  }
  if( (oldface2 = _model.fface(oldsolid,_f2)) == NULL)
  {
    std::cout << "mev: face " << _f2 << " not found in solid " << _s << ". \n";
    //return(ERROR);
  }
  if( (he1 = _model.fhe(oldface1,_v1, _v2)) == NULL)
  {
    std::cout << "mev: edge " << _v1 << " - " << _v2 << " not found in face " << _f1 << ". \n";
    //return(ERROR);
  }
  if( (he2 = _model.fhe(oldface2,_v1, _v3)) == NULL)
  {
    std::cout << "mev: edge " << _v1 << " - " << _v3 << " not found in face " << _f2 << ". \n";
    //return(ERROR);
  }
}
